﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.CodeDom.Compiler;
using Microsoft.CSharp;

namespace AssemblyExplorer
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {

        }

        private void cToolStripMenuItem_Click(object sender, EventArgs e)
        {
            openDLLFile.Filter = "Net 4.0 DLL files (*.dll)|*.dll|Net 4.0 Executable files (*.exe)|*.exe";
            openDLLFile.Title = "Explore what Assembly?";
            openDLLFile.ShowDialog();
            //Send all this info to our AssemblyDisplay
            AssemblyDisplay display = new AssemblyDisplay(openDLLFile.FileName);
            
        }

        private void sourceFilesView_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void readToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CompileDLL();
        }


        private void clearToolStripMenuItem_Click(object sender, EventArgs e)
        {
            sourceFilesView.Clear();
        }


        private void clearToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            dllFilesView.Clear();
        }


        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
            this.Dispose(true);
        }
        private void button1_Click(object sender, EventArgs e)
        {
            Scripter scripter = new Scripter();
            scripter.Show();
        }






        #region Custom Functions
        #region sourceFilesView
        /// <summary>
        /// Event to fire when files are dragged into the sourceFilesView list
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void sourceFilesView_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
                e.Effect = DragDropEffects.Copy;
        }

        /// <summary>
        /// Event to fire when files are dropped into
        /// the sourceFilesView List.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void sourceFilesView_DragDrop(object sender, DragEventArgs e)
        {
            string[] handles = (string[])e.Data.GetData(DataFormats.FileDrop, false);
            foreach (string s in handles)
            {
                if (File.Exists(s))
                {
                    if (string.Compare(Path.GetExtension(s), ".cs", true) == 0)
                    {
                        AddFileToListview(sourceFilesView, s);
                    }
                }
                else if (Directory.Exists(s))
                {
                    DirectoryInfo di = new DirectoryInfo(s);
                    FileInfo[] files = di.GetFiles("*.cs");
                    foreach (FileInfo file in files)
                        AddFileToListview(sourceFilesView ,file.FullName);
                }
            }
        }
        #endregion sourceFilesView
        #region dllFilesView
        /// <summary>
        /// Event to fire when files are dragged into the dllFilesView list
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void dllFilesView_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
                e.Effect = DragDropEffects.Copy;
        }

        /// <summary>
        /// Event to fire when files are dropped into
        /// the dllFilesView List.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void dllFilesView_DragDrop(object sender, DragEventArgs e)
        {
            string[] handles = (string[])e.Data.GetData(DataFormats.FileDrop, false);
            foreach (string s in handles)
            {
                if (File.Exists(s))
                {
                    if (string.Compare(Path.GetExtension(s), ".dll", true) == 0 || string.Compare(Path.GetExtension(s), ".exe", true) == 0)
                    {
                        AddFileToListview(dllFilesView, s);
                    }
                }
                else if (Directory.Exists(s))
                {
                    DirectoryInfo di = new DirectoryInfo(s);
                    FileInfo[] files = di.GetFiles("*.dll");
                    foreach (FileInfo file in files)
                        AddFileToListview(dllFilesView, file.FullName);
                }
            }
        }
        #endregion dllFilesView
        #region Misc
        /// <summary>
        /// Adds a file to the specified listview.
        /// </summary>
        /// <param name="list"></param>
        /// <param name="fullFilePath"></param>
        private void AddFileToListview(ListView list ,string fullFilePath)
        {
            if (!File.Exists(fullFilePath))
                return;
            string fileName = Path.GetFileName(fullFilePath);
            string dirName = Path.GetDirectoryName(fullFilePath);
            if (dirName.EndsWith(Convert.ToString(Path.DirectorySeparatorChar)))
                dirName = dirName.Substring(0, dirName.Length - 1);
            /* Grab the files icon, then create a ImageList to hold the icon
             * Then assign that image list to the listview - Pactor
             */
            Icon extractedIcon = System.Drawing.Icon.ExtractAssociatedIcon(fullFilePath);
            ImageList imageList = new ImageList();
            imageList.Images.Add(extractedIcon);
            list.SmallImageList = imageList;

            ListViewItem itmCheck = new ListViewItem(fullFilePath, imageList.Images.Count);
            itmCheck.Name = fullFilePath;
            if (list.Items.ContainsKey(itmCheck.Name))
            {

            }
            else
            {
                list.Items.Add(itmCheck);
                itmCheck.ImageIndex = imageList.Images.Count - 1;
            }

        }

        /// <summary>
        /// This function creates the .NET DLL
        /// </summary>
        /// <returns>true if created.</returns>
        public bool CompileDLL()
        {
            //Grab the info we need
            //Do we even have files in our list ?
            // or did the user just click the button first ?
            if (sourceFilesView.Items.Count <= 0)
            {
                MessageBox.Show("Drag files to compile into a dll, into the correct box.", "Error no files seclected!!");
                return false;
            }
            List<string> allFiles = new List<string>();
            string[] files;
            foreach (ListViewItem i in sourceFilesView.Items)
            {
                allFiles.Add(i.Name);
            }

            files = allFiles.ToArray();

            // Save to what dll name ?
            saveDLL.Filter = "Net 4.0 Dll (*.dll)|*.dll";
            saveDLL.Title = "Compile files into this DLL name.";
            saveDLL.ShowDialog();
            if (CompileFiles(files, saveDLL.FileName))
            {
                MessageBox.Show(saveDLL.FileName + " Sucessfully Created.");
                return true;
            }
            return false;
        }

        public bool CompileFiles(String[] files, string dllname)
        {
            /// <summary>
            /// Our CSharp compiler object
            /// </summary>
            CodeDomProvider compiler = new CSharpCodeProvider
                (new Dictionary<string, string> { { "CompilerVersion", "v4.0" } });
            // Referenced assemblies tied into form listview.
            List<string> refAssemblies = new List<string>();
            if (!refAssemblies.Contains("System.Core.dll")) { refAssemblies.Add("System.Core.dll"); }
            foreach (ListViewItem i in dllFilesView.Items)
            {
                refAssemblies.Add(i.Name);
            }


            /// <summary>
            /// Our compiler parameter command line to pass 
            /// when we compile the scripts.
            /// </summary>
            CompilerParameters p = new CompilerParameters
            {
                GenerateInMemory = false,
                GenerateExecutable = false,
                IncludeDebugInformation = true,
                OutputAssembly = string.Format(dllname),
                TreatWarningsAsErrors = false,
                WarningLevel = 3,
                CompilerOptions = "/optimize"
            };
            foreach (string s in refAssemblies) { p.ReferencedAssemblies.Add(s); }
            CompilerResults results;

            try
            {
                results = compiler.CompileAssemblyFromFile(p, files);
                if (results.Errors.HasErrors)
                {
                    var errorText = new StringBuilder();
                    var count = results.Errors.Count;
                    for (var i = 0; i < count; i++)
                    {
                        errorText.AppendLine("Compilation Error: " + results.Errors[i].ErrorText);
                    }
                    MessageBox.Show(errorText.ToString());
                    return false;
                }
            }
            catch (Exception compileException)
            {
                MessageBox.Show(compileException.ToString(), "Error in Compilation!!");
            }
            return true;
        }
        #endregion Misc


        #endregion

    }
}
